#include "html_string.hpp"
#include <cstddef>
#include <cstdlib>
#include <exception>
#include <format>
#include <iostream>
#include <ostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <string_view>
#include <unordered_set>
#include <utility>
#include <vector>
#include <webview/backends.hh>
#include <webview/webview.h>

extern char** environ;

using vpss_t = std::vector<std::pair<std::string, std::string>>;
vpss_t getEnvKv(){
    vpss_t result;
    for(char **env = environ; *env != nullptr; env++){
        const std::string thisEnv = *env;
        const size_t idx = thisEnv.find('=');
        if (idx == std::string::npos) {
            throw std::logic_error("cannot parse env");
        }
        result.emplace_back(thisEnv.substr(0,idx),thisEnv.substr(idx+1));
    }
    return result;
}

template<class T,class U>
std::ostream&operator<<(std::ostream &os,const std::pair<T,U> &p){
    os<<"{ "<<p.first<<", "<<p.second<<" }";
    return os;
}

template<class T>
std::ostream&operator<<(std::ostream &os,const std::vector<T> &v){
    os<<"[ ";
    if(v.size()==1){
        os<<v[0]<<" ]";
        return os;
    }
    for(size_t i=0;i<v.size()-1;i++){
        os<<v[i]<<", ";
    }
    os<<" ]";
    return os;
}

std::string envKvToJsonString(const vpss_t &v){
    std::stringstream ss;
    const auto toJsonString = [](const std::string_view &str)->std::string{
        std::stringstream ss;
        for(size_t i=0;i<str.size();i++){
            const std::unordered_set<char> set={'\\','\"'};
            if(set.find(str[i])!=set.end()){
                ss<<"\\";
            }
            ss<<str[i];
        }
        return ss.str();
    };
    if(v.size()==0)return "{}";
    ss<<"{";
    if(v.size()==1){
        ss<<"\""<<toJsonString(v[0].first)<<"\":\""<<toJsonString(v[0].second)<<"\"}";
        return ss.str();
    }
    for(size_t i = 0;i<v.size()-1;i++){
        ss<<"\""<<toJsonString(v[i].first)<<"\":\""<<toJsonString(v[i].second)<<"\",";
    }
    ss<<"\""<<toJsonString(v[v.size()-1].first)<<"\":\""<<toJsonString(v[v.size()-1].second)<<"\"}";
    return ss.str();
}

int main(const int argc,char *argv[]){
    try {
        webview::webview wv(true,nullptr);
        wv.set_title("eew -- Env viewer by Tudor");
        wv.bind("getEnvString",
            [](const std::string &req)->std::string {
                std::cout<<envKvToJsonString(getEnvKv())<<'\n';
                return envKvToJsonString(getEnvKv());
            });
        wv.set_html(html);
        wv.run();
    } catch (const std::exception &e) {
        std::cerr<<e.what()<<'\n';
        return 1;
    }
}